#include "device.h"
#include "component.h"
#include "stk3x3x.h"
#ifdef IR_SENSOR_YIMING
#include "mn25713.h"
#endif
#define IRSENSOR_LOG(format, ...)  __OSAL_LOG("[IRsensor.c] " C_BLUE format C_NONE, ##__VA_ARGS__)


#define VHW_PIN_IR_POWER vPIN_C6
#define VHW_IIC_IR       vIIC_0

#define EVENT_READ_STK (0X00000001)
#define EVENT_IRERR_PUBLISH (0X00000002)
#define SHAKE_TIMES 5
#define SHAKE_TIMEOUT 20

static uint8_t activeFlag = 2;  //0:松开，1：按下,2:不确定
static uint8_t ir_err = 0;
static uint8_t timeoutFlag = 0; //超时检测标志位
static int timeout_cnt = 0;
#ifdef IR_SENSOR_YIMING
static uint8_t activeFlag_1 = 2;  //0:松开，1：按下,2:不确定
static uint8_t ir_err_1 = 0;
static uint8_t timeoutFlag_1 = 0; //超时检测标志位
static int timeout_cnt_1 = 0;
#endif
/**
  * @brief  
  *         
  * @note   
  */
static void Stk_ReadDistance(void)
{
    static uint8_t count = 0, count_rele = 0;
    
    IRsensorMsg_t msg;
    #ifdef IR_SENSOR_YIMING
    msg.addr = (uint32_t)IIC_ADDR_STK;
    #endif
    msg.distance = STK_Read_PS();
    #ifdef STK3311_X
    if (msg.distance > 1000)
    #else
    if (msg.distance > 20000)
    #endif
    {
        if(activeFlag != 1)
        {
            printf("count %d:%d\r\n",count,msg.distance);
        } 
        if (++count >= SHAKE_TIMES)
        {
            count = 0;

            if((++timeout_cnt >= SHAKE_TIMEOUT) && (timeoutFlag != 1))      //超时5s
            {
                timeoutFlag = 1;
                timeout_cnt = 0;
                IRSENSOR_LOG("stk (%d),timeout...........\r\n", msg.distance);
                msg.action = USER_ACTION_RELEASE;
                OSAL_MessagePublish(&msg, sizeof(IRsensorMsg_t));
                OSAL_SetTaskStatus(TASK_STA_NORMAL);
            }

            if (activeFlag != 1)
            {
                OSAL_SetTaskStatus(TASK_STA_ACTIVE);
                IRSENSOR_LOG("stk is press(%d)\r\n", msg.distance);
                msg.action = USER_ACTION_PRESS;
                OSAL_MessagePublish(&msg, sizeof(IRsensorMsg_t));
            }

            activeFlag = 1;
        }

    }
    else
    {
        timeoutFlag = 0;
        timeout_cnt = 0;
        count = 0;
        if ((activeFlag != 0) && (++count_rele >= SHAKE_TIMES))
        {
            count_rele = 0;
            OSAL_SetTaskStatus(TASK_STA_NORMAL);
            IRSENSOR_LOG("stk is release\r\n");
            msg.action = USER_ACTION_RELEASE;
            OSAL_MessagePublish(&msg, sizeof(IRsensorMsg_t));
            activeFlag = 0;
        }
    }
}
#ifdef IR_SENSOR_YIMING
/**
  * @brief  
  *         
  * @note   
  */
static void MN_ReadDistance(void)
{
    static uint8_t count = 0, count_rele = 0;
    IRsensorMsg_t msg;
    msg.addr = (uint32_t)IIC_ADDR_MN;
    msg.distance = MN_Read_PS();
    if (msg.distance > 500)
    {
        if(activeFlag_1 != 1)
        {
            printf("count %d:%d\r\n",count,msg.distance);
        } 
        if (++count >= SHAKE_TIMES)
        {
            count = 0;
            if((++timeout_cnt_1 >= SHAKE_TIMEOUT) && (timeoutFlag_1 != 1))      //超时5s
            {
                timeoutFlag_1 = 1;
                timeout_cnt_1 = 0;
                IRSENSOR_LOG("MN (%d),timeout...........\r\n", msg.distance);
                msg.action = USER_ACTION_RELEASE;
                OSAL_MessagePublish(&msg, sizeof(IRsensorMsg_t));
                OSAL_SetTaskStatus(TASK_STA_NORMAL);
            }
            if (activeFlag_1 != 1)
            {
                OSAL_SetTaskStatus(TASK_STA_ACTIVE);
                IRSENSOR_LOG("mn is press(%d)\r\n", msg.distance);
                msg.action = USER_ACTION_PRESS;
                OSAL_MessagePublish(&msg, sizeof(IRsensorMsg_t));
            }
            activeFlag_1 = 1;
        }
    }
    else
    {
        timeoutFlag_1 = 0;
        timeout_cnt_1 = 0;
        count = 0;
        if ((activeFlag_1 != 0) && (++count_rele >= SHAKE_TIMES))
        {
            count_rele = 0;
            OSAL_SetTaskStatus(TASK_STA_NORMAL);
            IRSENSOR_LOG("mn is release\r\n");
            msg.action = USER_ACTION_RELEASE;
            OSAL_MessagePublish(&msg, sizeof(IRsensorMsg_t));
            activeFlag_1 = 0;
        }
    }
}
#endif
/**
  * @brief  IR传感器任务函数
  *
  * @param  event：当前任务的所有事件
  *
  * @return 返回未处理的事件
  */
static uint32_t IRsensor_Task(uint32_t event)
{
    /* 系统启动事件 */
    if (event & EVENT_SYS_START)
    {
        IRsensorMsg_t msg;
        IRSENSOR_LOG("IRsensor task start\r\n");

        /* 打开传感器 */
        Device_Write(VHW_PIN_IR_POWER, 0, 0, 1);
        Device_DelayMs(1);
        Device_Enable(VHW_IIC_IR);

        if(STK_Get_sensortype()!= 0)
        {
            STK_SoftPowerOn();
        }
        #ifdef IR_SENSOR_YIMING
        if(MN_Get_sensortype()!= 0)
        {
            MN_SoftPowerOn();
        }
        #endif
        if(STK_Get_sensortype()!= 0)
        {
            ir_err = 0;
            OSAL_EventRepeatCreate(COMP_IRSENSOR, EVENT_READ_STK, 30, EVT_PRIORITY_LOW);
        }
        else
        {
            ir_err = 1;
            printf("sensor init error\r\n");
        }
        OSAL_EventSingleCreate(COMP_IRSENSOR, EVENT_IRERR_PUBLISH, 1000, EVT_PRIORITY_MEDIUM);

        return (event ^ EVENT_SYS_START);
    }

    /* 系统休眠事件 */
    if (event & EVENT_SYS_SLEEP)
    {

        IRSENSOR_LOG("IRsensor task sleep\r\n");
        activeFlag = 2;

        /* 关闭传感器 */
        if(STK_Get_sensortype()!= 0)
        {
            OSAL_EventDelete(COMP_IRSENSOR,EVENT_READ_STK);
            STK_SoftPowerOff();
        }
        timeoutFlag = 0;
        timeout_cnt = 0;

        #ifdef IR_SENSOR_YIMING
        activeFlag_1 = 2;
        if(MN_Get_sensortype()!= 0)
        {
            MN_SoftPowerOff();
        }
        timeoutFlag_1 = 0;
        timeout_cnt_1 = 0;
        #endif

        Device_Disable(VHW_IIC_IR);
        Device_Write(VHW_PIN_IR_POWER, 0, 0, 0);
        
        return (event ^ EVENT_SYS_SLEEP);
    }

    /* 测距事件 */
    if (event & EVENT_READ_STK)
    {
        Stk_ReadDistance();
        #ifdef IR_SENSOR_YIMING
        MN_ReadDistance();
        #endif
        return (event ^ EVENT_READ_STK);
    }

    if (event & EVENT_IRERR_PUBLISH)
    {
        OSAL_MessagePublishErrorCode(ERRCODE_TYPE_IRSENSOR, ir_err);
        
        return ( event ^ EVENT_IRERR_PUBLISH );
    }

    return 0;
}
COMPONENT_TASK_EXPORT(COMP_IRSENSOR, IRsensor_Task, 0);
